package cn.com.scitc.licenseplateback.controller;

import cn.com.scitc.licenseplateback.dao.LdleParkingDao;
import cn.com.scitc.licenseplateback.dao.MembershipInformationDao;
import cn.com.scitc.licenseplateback.model.LdleParkingEntity;
import cn.com.scitc.licenseplateback.model.MembershipInformationEntity;
import cn.com.scitc.licenseplateback.redis.RedisUtil;
import cn.com.scitc.licenseplateback.token.TokenFactory;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.util.List;
import java.util.Map;

@Component
public class PublicFunction {

    /**
     * 日志
     */
    private Log log = LogFactory.getLog(getClass());


    /**
     * 缓存库
     */
    @Autowired
    private RedisUtil redisUtil;

    /**
     * token 生成工厂
     */
    @Autowired
    private TokenFactory tokenFactory;

    /**
     * 会员信息处理
     */
    @Autowired
    private MembershipInformationDao membershipInformationDao;

    /**
     * 查询各立方库的剩余车位信息
     */
    @Autowired
    private LdleParkingDao ldleParkingDao;




    /**
     * ******************************************以上为注入实例***************************************************
     */


    /**
     * 根据传入的 请求头 解析请求头中的 token 信息
     * 将 token 信息完整的以JSONObject 形式返回
     * @param request 请求头
     * @return JSONObject 对象
     */
    public JSONObject getServerToken(HttpServletRequest request){
        String token = request.getHeader("cubelibrarytoken");
        String tokenInfo = redisUtil.get(token).toString();
        if(tokenInfo == ""){return new JSONObject();};
        JSONArray jsonArray = JSONArray.parseArray(tokenInfo);
        JSONObject jsonObject = JSONObject.parseObject(jsonArray.get(0).toString());
        return jsonObject;
    }

    /**
     * 根据传入的 请求头 解析请求头中的 token 信息
     * 获取用户 ID 生成文件名，并在批定目录中生成文件夹，并以返回数组
     * @param request 请求头
     * @return [ filePath，fileName]
     */
    public String[] getUserPhotoFilePath(HttpServletRequest request) {
        JSONObject serverToken = getServerToken(request);
        String filePath = "src/main/resources/static/UserPhotos";
        File readPath = new File(filePath);
        if (!readPath.exists() && !readPath.isDirectory()) {
            readPath.mkdir();
            log.info("创建文件夹路径为: " + readPath);
        }
        String fileName = serverToken.getString("userId") + ".txt";
        return new String[]{filePath, fileName};
    }


    /**
     * 用户登录成功后，将用户的身份和姓名传入 TokenFactory 中进行封装
     * 将封装好的 Token 的键和值写入到 Redis 缓存中，并设置过期时间
     * 最后将 Token 的键返回
     *
     * @param Account 身份证
     * @param Name    姓名
     * @param request 获取请求头-提取设备类型
     * @return key
     */
    public String saveTokenFactoryRedis(String Account, String Name, HttpServletRequest request) {
        // 将用户的信息传入 TokenFactory 进行封装
        String tokenKey = tokenFactory.setTokenKey(Account, Name);
        List<Map> tokenValue = tokenFactory.setTokenValue(Account, request);
        // 将用户登录信息存入缓存
        redisUtil.set(tokenKey, JSONObject.toJSONString(tokenValue));
        redisUtil.expire(tokenKey, 3600);
        return tokenKey;
    }

    /**
     * 根据传入的 验证码 ，并解析请求头中的 token
     * 获取用户的手机号即为服务端的 key
     * 最后以 key-value 取值进行核验
     * @param Code 验证码
     * @param request 请求头
     * @return success or error
     */
    public String checkPhoneVerificationCode(String Code, HttpServletRequest request){
        JSONObject serverToken = getServerToken(request);
        MembershipInformationEntity memberInfo = membershipInformationDao.findbyMember(serverToken.get("userId").toString());
        String serverCode = redisUtil.get(memberInfo.getCellPhoneNumber()).toString();
        if (serverCode.equals(Code)){
            return "success";
        }
        return "error";
    }

    /**
     * 根据用户传入 车位信息 和 命令
     * 对车位信息表 车位进行 添加(add) 或 移除(remove)
     * @param parkingString 车位信息
     * @param command 命令 add / remove
     */
    public void analyzeParkingInformation(String parkingString, String command){
        // 车位分解
        String [] parking = parkingString.split("-");
        // 立方库编号
        String libraryNumber = parking[0] + "-" + parking[1];
        // 区域
        String region = parking[2];
        // 楼层
        int arrangement = Integer.valueOf(parking[3]);
        // 根据编号、区域、楼层 查询车位信息
        LdleParkingEntity parkingInfo = ldleParkingDao.findByCRA(libraryNumber, region, arrangement);
        // 将字符数组 转 java 数组
        JSONArray jsonArray = JSONArray.parseArray(parkingInfo.getNumber());

        if(command.equals("remove")){
            // 查询数组中匹配车位 => 移除(被预约)
            for(int i = 0 ; i < jsonArray.size() ; i++){
                if(jsonArray.get(i).toString().equals(parking[4])){
                    Object remove = jsonArray.remove(i);
                }
            }
        }else if(command.equals("add")){
            // 向数组中添加车位 => 出库或超时
            jsonArray.add(Integer.valueOf(parking[4]));
        }

        // 将 java 数组 转 数组字符串
        String jsonString = JSONArray.toJSONString(jsonArray);
        // 将根据编号、区域、楼层 查询车位信息 更改车位信息后，保存
        parkingInfo.setNumber(jsonString);
        // 更新车位信息
        ldleParkingDao.save(parkingInfo);
    }
}
